# encoding: utf-8
"""
@author: youfeng
@file: proxy_lock_dao.py
@time: 2018/8/14 下午10:47
"""

# 代理存储管理
import copy
import json
import time

import redis

from common.util import Util
from enum.proxy_key import ProxyKey


class ProxyDAO(object):

    def __init__(self, redis_conf, log=None):
        self.log = log
        # 初始化redis
        self.__redis_temp_handler = redis.StrictRedis(host=redis_conf['host'],
                                                      port=redis_conf['port'],
                                                      db=redis_conf['db'],
                                                      password=redis_conf['password'],
                                                      max_connections=redis_conf['max_connections'])

    # 从redis中获取所有的代理
    def get_proxy_list_from_redis(self, redis_key):
        proxy_list = []
        start_time = time.time()

        try:
            proxy_temp_list = self.__redis_temp_handler.lrange(redis_key, 0, -1)
            for proxy_str in proxy_temp_list:
                proxy_dict = json.loads(proxy_str)
                if not isinstance(proxy_dict, dict):
                    self.log.error("代理结构异常: proxy_str = {}".format(proxy_str))
                    continue

                expire_time = proxy_dict.get(ProxyKey.EXPIRE_TIME_KEY)
                if expire_time is None:
                    self.log.error("获取代理过期时间失败: {}".format(proxy_str))
                    continue

                proxy_dict[ProxyKey.EXPIRE_TIME_KEY] = Util.time_to_timestamp(expire_time)
                proxy_list.append(proxy_dict)
        except Exception as e:
            self.log.error("获取redis中代理异常: key = {}".format(redis_key))
            self.log.exception(e)

        self.log.info("获取代理耗时: {} s".format(round(time.time() - start_time, 2)))
        return proxy_list

    # 存储代理到redis
    def set_proxy_list_to_redis(self, redis_key, proxy_list):
        start_time = time.time()
        pipe = self.__redis_temp_handler.pipeline()
        copy_proxy_list = copy.deepcopy(proxy_list)
        for proxy_dict in copy_proxy_list:
            try:
                # 再存储列表到redis
                expire_time = proxy_dict.get(ProxyKey.EXPIRE_TIME_KEY)
                if expire_time is None:
                    self.log.error("当前代理没有设置过期时间: proxy_dict = {}".format(proxy_dict))
                    continue

                proxy_dict[ProxyKey.EXPIRE_TIME_KEY] = Util.timestamp_to_time(expire_time)

                pipe.rpush(redis_key, json.dumps(proxy_dict))
            except Exception as e:
                self.log.error("存储代理到redis 异常: ")
                self.log.exception(e)

        pipe.execute()
        self.log.info("存储代理耗时: num = {} {} s".format(len(proxy_list), round(time.time() - start_time, 2)))

    # 删除redis中已经存储的代理信息
    def delete_redis_proxy_list(self, redis_key):
        self.__redis_temp_handler.delete(redis_key)

    # 存储代理到set中
    def set_proxy_set_to_redis(self, redis_key, proxy_list):
        start_time = time.time()
        pipe = self.__redis_temp_handler.pipeline()
        for proxy_dict in proxy_list:
            try:

                proxy = proxy_dict.get(ProxyKey.PROXY_KEY)
                ip = Util.get_ip_from_proxy(proxy)
                if ip is None:
                    self.log.error("获取IP失败: proxy = {}".format(proxy_dict))
                    continue
                pipe.sadd(redis_key, ip)
            except Exception as e:
                self.log.error("存储代理到redis 异常: ")
                self.log.exception(e)

        pipe.execute()
        self.log.info("存储代理耗时: num = {} {} s".format(len(proxy_list), round(time.time() - start_time, 2)))

    # 设置过期时间
    def set_expire_time(self, redis_key, ex_time):
        try:
            self.__redis_temp_handler.expireat(redis_key, ex_time)
        except Exception as e:
            self.log.error("设置过期时间失败: redis_key = {}".format(redis_key))
            self.log.exception(e)
